home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1995 November
/
EnigmA AMIGA RUN 02 (1995)(G.R. Edizioni)(IT)[!][issue 1995-11][Skylink CD].iso
/
earcd
/
ead
/
ead23.dms
/
ead23.adf
/
Listati
/
Calc.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-05-29
|
7KB
|
217 lines
/* **************************************************************
Programma ...... Calc.c
Versione ....... 2.01, 1 Maggio 1990
Scopo .......... Calcolo di espressioni ASCII con numeri f.p.
Autore ......... Luigi Callegari. Fidonet: 2:331/101.0 (AmnesiA)
Hardware ....... Amiga standard 500/2500, Kickstart V1.2/1.3/1.4
Software ....... Lattice C V5.04, Aztec C V5.0a
Make Lattice ... LC -vbr -Lntvm -O -fi -ms Calc
Make Aztec ..... CC -fa -sb -so Calc, LN calc -lma -lc
************************************************************** */
#define MAXOPL 5 /* Massimo numero di livelli */
#define MAXELE 50 /* Massimo numero di operandi aritmetici */
#define NOP 0 /* Token di "nessuna operazione" */
#define ADD 1 /* Token di somma aritmetica */
#define SUB 2 /* Token di sottrazione aritmetica */
#define MUL 3 /* Token di moltiplicazione aritmetica */
#define DIV 4 /* Token di divisione aritmetica */
#define POW 5 /* Token di elevazione a potenza */
#define PRIOR POW /* Operazione prioritaria per importanza */
#define isoper(c) (c=='+'||c=='-'||c=='/'||c=='*'||c=='^')
#include <string.h> /* Funzioni di gestione stringa */
#include <stdlib.h> /* Funzioni di libreria standard */
#include <ctype.h> /* Funzioni isxxxx() */
#include <stdio.h> /* I/O Standard */
#include <math.h> /* Matematica */
#include <libraries/dos.h> /* Gestione AmigaDOS */
#ifdef LATTICE
# include <proto/all.h>
#else
# include <functions.h>
#endif
double num[ MAXELE ]; /* Matrice Operandi */
int op[ MAXELE ][ MAXOPL ]; /* Matrice Operatori aritmetici */
int lev; /* Livello operatori */
int nop; /* Numero effettivo operatori */
int nel; /* Numero effettivo operandi */
char *buf; /* Buffer per elaborazione batch */
BPTR lucc; /* Lock di file */
/* ******** Uscita da errore con messaggio di postmortem ****** */
void die( char *s ) /* Puntatore a messaggio di errore */
{
if ( lucc ) UnLock( lucc );
fprintf( stderr, "\n%s\n", s );
exit( 10L );
}
/* Ritorna lunghezza in caratteri di una stringa ASCII rappresentante
un numero in virgola mobile, con eventuale notazione esponenziale */
int luncifra( char *s )
{
int j = 0;
while ( isdigit( s[ j ] ) ) ++j; /* Salta parte intera */
if ( s[ j ] == '.' )
{
++j;
while ( isdigit( s[ j ] ) ) ++j; /* Salta eventuali decimali */
}
if ( s[ j ] == 'e' || s[ j ] == 'E' )
{
++j; /* Salta parte esponenziale */
if ( s[ j ] == '+' || s[ j ] == '-' )
++j;
while( isdigit( s[ j ] ) ) ++j;
}
return( j );
}
/* ************ Corregge matrici dopo una operazione ********** */
void compr( int *k ) /* Puntatore a posizione di operando usato */
{
unsigned short int j, i; /* Variabili di lavoro */
--nop; --nel; /* Aggiusta contatori di operatori e operandi */
for ( j=*k ; j<nel ; j++ ) /* Elimina operando usato */
num[ j+1 ] = num[ j+2 ];
for ( i=0 ; i<MAXOPL ; i++ ) /* Elimina operatore usato */
for ( j=*k ; j<nop ; j++ )
op[ j ][ i ] = op[ j+1 ][ i ];
*k -= 1; /* Riporta puntatore scansione a posizione corretta */
return;
}
/*************** Memorizza operandi ed operatori ***************/
void parse( char *s ) /* Stringa ASCII dell'espressione */
{
int c; /* Carattere da esaminare */
int j; /* Variabili di lavoro */
short operation; /* Operazione da eseguire */
for ( j=0 ; j<strlen(s) ; j++ ) {
c = s[ j ];
if ( c == ')' && --lev < 0 )
die( "Troppe parentesi chiuse!" );
else if ( c == '(' && ++lev == MAXOPL )
die( "Troppe parentesi aperte!" );
else if ( isoper( c ) ) { /* Memorizza operatore */
switch( c ) {
case '^' : operation = POW; break;
case '+' : operation = ADD; break;
case '-' : operation = SUB; break;
case '*' : operation = MUL; break;
case '/' : operation = DIV; break;
default : operation = NOP; break;
} /* end switch(c) */
op[ nop++ ][ lev ] = operation;
} /* end else if() */
else if ( isdigit( c ) ) { /* Memorizza operando */
num[ nel++ ] = (double) atof( &s[ j ] );
if ( nel >= MAXELE )
die( "Troppi operandi!" );
j += luncifra( &s[ j ] ) - 1; /* Salta numero inserito */
} /* end else if */
} /* end for (j) */
return;
} /* end parse() */
/************ Esegue materialmente i calcoli ***************/
double calc( char *s ) /* Puntatore a stringa di espressione */
{
int j, i;
(void)parse( s ); /* Crea matrici operandi e operatori */
for ( lev=MAXOPL-1 ; lev>=0 ; lev-- ) /* Da livello massimo */
{
for ( j=PRIOR ; j >= ADD ; j-- ) /* Da oper. prioritaria */
for ( i=0 ; i < nop; i++ ) /* Da primo operatore */
if ( op[ i ][ lev ] == j )
{
switch( op[ i ][ lev ] ) {
case DIV: num[ i ] /= num[ i+1 ]; break;
case MUL: num[ i ] *= num[ i+1 ]; break;
case ADD: num[ i ] += num[ i+1 ]; break;
case SUB: num[ i ] -= num[ i+1 ]; break;
case POW: num[ i ] = pow(num[i],num[i+1]);break;
default : break;
} /* end switch */
compr( &i ); /* Aggiorna matrici */
} /* end if */
} /* end for (lev) */
return( num[ 0 ] );
}
/* ********** Funzione trasferimento file in buffer ************ */
char *makebuf( char *s )
{
struct FileInfoBlock *fib;
char *ptr;
LONG lunfile;
BPTR fileh;
if (!(lucc=Lock(s, ACCESS_READ) ) ) die("Locking impossibile!");
if (!(fib=(struct FileInfoBlock*)malloc(sizeof(struct FileInfoBlock))))
die( "Manca memoria per FIB" );
if ( ! Examine( lucc, (BPTR) fib ) ) die( "Non esamino file!" );
lunfile = fib -> fib_Size; UnLock( lucc ); lucc = (BPTR) NULL;
if ( ! (ptr = (char *) malloc( lunfile ) ) ) die("Manca memoria");
if ( ! (fileh=Open( s, MODE_OLDFILE ))) die("Non si apre il file");
if ( Read( fileh, ptr, lunfile ) != lunfile) die("Errore di I/O");
Close( fileh );
return( ptr );
}
/************ Funzione principale *****************/
void main( int argc, char *argv[] )
{
if ( argc != 2 ) { /* Sintassi errata */
printf( "\nSintassi: %s [expr]\n", argv[ 0 ] );
exit( 10L );
}
if ( isalpha( argv[1][0] )) /* Dato un nome di file */
printf("File %s = %.8g\n", argv[1], calc(makebuf(argv[1])));
else /* Data un'espressione */
printf( "%s = %.8g\n", argv[ 1 ], calc( argv[ 1 ] ) );
exit( 0L );
}